﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="MainWindow.xaml.cs" company="Jarno Burger">
//   Jarno Burger
// </copyright>
// <summary>
//   Interaction logic for MainWindow.xaml
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace MyDomotica
{
    using System;
    using System.Threading;
    using System.Windows;
    using System.Windows.Threading;

    using MyDomotica.Model;

    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        #region Declare
        /// <summary>
        /// The class that takes care of showing data on the user interface.
        /// </summary>
        private readonly UserInterfaceShowData userInterfaceShowData;

        /// <summary>
        /// The class that takes care of pushing data to the internet.
        /// </summary>
        private readonly InternetPush internetPush;

        /// <summary>
        /// The class that takes care of communicating with the arduino.
        /// </summary>
        private readonly Arduino arduino;

        /// <summary>
        /// The class that takes care of turning the heater on or off.
        /// </summary>
        private readonly Heater heater;

        /// <summary>
        /// The class that contains all the current data, the model.
        /// </summary>
        private readonly Model.Model model;

        /// <summary>
        /// Is false while the program can run. Is true when the program must stop.
        /// </summary>
        private readonly bool breakExecution;
        #endregion

        #region Initialize
        /// <summary>
        /// Initializes a new instance of the <see cref="MainWindow"/> class.
        /// </summary>
        public MainWindow()
        {
            this.InitializeComponent();

            this.breakExecution = false;

            this.model = new Model.Model();

            this.userInterfaceShowData = new UserInterfaceShowData(this, this.model);

            this.internetPush = new InternetPush(this.model);
            this.internetPush.EventDebug += this.OnDebugMessage;

            this.arduino = new Arduino(this.Model);
            this.arduino.EventDebug += this.OnDebugMessage;

            this.heater = new Heater(this.model);
            this.heater.EventDebug += this.OnDebugMessage;
        }

        /// <summary>
        /// Called when this window is in [load] modus.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="RoutedEventArgs"/> instance containing the event data.</param>
        private void OnLoad(object sender, RoutedEventArgs e)
        {
            var work = new Thread(this.DoWork);
            work.Start();
        }
        #endregion

        #region Properties
        /// <summary>
        /// Gets the model. This contains all the current data.
        /// </summary>
        /// <value>
        /// The model.
        /// </value>
        public Model.Model Model
        {
            get
            {
                return this.model;
            }
        }
        #endregion

        #region Handle Events
        /// <summary>
        /// This handles when the debug event is called.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="message">The message.</param>
        private void OnDebugMessage(object sender, string message)
        {
            var name = sender.GetType().Name;
            var line = name + " : " + message;

            System.Diagnostics.Debug.WriteLine(line);

            this.model.CurrentMessage = line;
        }
        #endregion

        /// <summary>
        /// Does the main work , calls each worker class to do stuff..
        /// </summary>
        private void DoWork()
        {
            // Application.DoEvents();

            // make a connection
            this.arduino.InitializeCommunication();

            // userInterfaceShowData.Update();
            // this.internetPush.Update();

            //// start the main-loop
            var counter = Constants.InternetPushInterval;
            while (this.breakExecution == false)
            {
                counter = counter - Constants.MainLoopWaitStepTime;
                this.UpdateUserInterface(counter);

                if (counter <= 0)
                {
                    this.internetPush.Update();
                    this.heater.Update();
                    this.arduino.KeepCommunicationAlive();

                    counter = Constants.InternetPushInterval;
                }

                // this.Model.Message = counter.ToString();
                Thread.Sleep(Constants.MainLoopWaitStepTime);
            }
        }

        /// <summary>
        /// Updates the user interface.
        /// </summary>
        /// <param name="counter">The counter.</param>
        private void UpdateUserInterface(float counter)
        {
            // todo : must move to user interface class..
            var percentage = counter / Constants.InternetPushInterval;
            var value = (1 - percentage) * 100f;
            this.Model.CurrentInternetPushProgress = (int)value;

            // System.Diagnostics.Debug.WriteLine("value is " + value);
            this.Dispatcher.Invoke(DispatcherPriority.Normal, (Action)(() => this.userInterfaceShowData.Update()));
        }
    }
}
